package com.hfb.mashibing.alip8.jvm.c2_classloader;

import java.io.*;

/** 通过自定义 ClassLoader 加密class文件，防止反编译
 *
 * @author hfb
 */
public class T007_CustomClassLoaderWithEncription extends ClassLoader {

    public static int seed = 0B10110110;

//    String loadClassBasePath = "/Users/baiwang/git_hfb/tianyaxunai/alibaba-p8/target/classes";
    public static String loadClassBasePath = "/Users/baiwang/git_hfb/tianyaxunai/alibaba-p8/src/main/java";
    public static String loadClassPackagePath = "com.hfb.mashibing.alip8.jvm.classloader.HelloWorld";
    public static String filePath = loadClassBasePath;

    public static void main(String[] args) throws Exception {
        // 生成加密 class
        T007_CustomClassLoaderWithEncription.encFile(loadClassPackagePath);

        // 加载进来
        ClassLoader classLoader = new T007_CustomClassLoaderWithEncription();
        Class clazz = classLoader.loadClass(loadClassPackagePath);

        //反射调用方法
        HelloWorld h = (HelloWorld) clazz.newInstance();
        h.sayHello(null);


        System.out.println(classLoader.getClass().getClassLoader());
        System.out.println(classLoader.getParent());

    }

    @Override
    public Class<?> findClass(String className) throws ClassNotFoundException {
        File f = new File(filePath, className.replaceAll("\\.", File.separator).concat(".hfbclass"));
        try (FileInputStream fin = new FileInputStream(f);
            ByteArrayOutputStream baos = new ByteArrayOutputStream()) {

            int b = 0;
            while ((b = fin.read()) != 0) {
                baos.write(b ^ seed);
            }
            byte[] bytes = baos.toByteArray();

            return defineClass(className, bytes, 0, bytes.length);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return super.findClass(className);
    }

    /** 加密方法
     *
     * @param className
     * @throws IOException
     */
    public static void encFile(String className) throws IOException {
        File f = new File(filePath, className.replaceAll("\\.", File.separator).concat(".class"));
        FileInputStream fis = new FileInputStream(f);
        FileOutputStream fos = new FileOutputStream(
                                    new File(
                                            filePath,
                                            className.replaceAll("\\.", File.separator).concat(".hfbclass")));

        int b = 0;
        while ((b = fis.read()) != -1) {
            fos.write(b ^ seed);
        }
        fis.close();
        fos.close();
    }


}
